<?php
/**
 * @author spenceryg
 * @date 2022/12/8
 * @time 8:22 下午
 * @focus love & life
 */


namespace app\auto\controller;


use app\auto\model\MethodFiled;
use think\facade\View;
use think\helper\Str;
use think\response\Json;

class Method extends \app\BaseController
{
    public function index()
    {
        $controller_id = input('controller_id');
        $data = \app\auto\model\Method::where('controller_id', $controller_id)->select();
        View::assign('data', $data);
        return View::fetch();
    }

    public function add()
    {
        if (request()->isPost()) {
            $data = input();
            validate([
                'type|方法类型' => 'require',
                'request|请求类型' => 'require',
                'comment|方法中文名' => 'require',
                'name|方法英文名' => 'require',
                'is_user_define|是否自定义' => 'require',
            ])->check($data);
            $find = \app\auto\model\Method::where('name', $data['name'])
                ->where('controller_id', $data['controller_id'])->find();

            if ($find) {
                return error('方法已经存在');
            }

            $this->addProgress($data);

            return success();


        } else {
            $controller_id = input('controller_id');
            $controller = \app\auto\model\Controller::find($controller_id);
            $table_name = Str::snake($controller->name);
            $table_name = env('DATABASE.PREFIX') . $table_name;
            $table_id = \app\auto\model\Table::where('name', $table_name)->value('id');
            $fields = \app\auto\model\Field::where('table_id', $table_id)->select();
            View::assign('table_name', $table_name);
            View::assign('fields', $fields);
            $tables = \app\auto\model\Table::select();
            View::assign('tables', $tables);
            return View::fetch();
        }
    }

    private function addProgress($data)
    {
        if ($data['msg'] === '') {
            unset($data['msg']);
        }
        if ($data['width'] === '') {
            unset($data['width']);
        }
        if ($data['height'] === '') {
            unset($data['height']);
        }
        $method = \app\auto\model\Method::create($data);

        $controller = \app\auto\model\Controller::find($data['controller_id']);
        $self_table_name = env('DATABASE.PREFIX') . Str::snake($controller['name']);
        foreach ($data['in_tables'] as $i => $table_name) {
            $this_method_filed = [];
            if (!$table_name || !$data['in_fields'][$i]) {
                continue;
            }
            $this_table = \app\auto\model\Table::getByName($table_name);
            $field = \app\auto\model\Field::where('name', $data['in_fields'][$i])->where('table_id', $this_table['id'])->find();
            $this_method_filed['field_id'] = $field['id'];
            $this_method_filed['condition'] = $data['in_conditions'][$i];
            $this_method_filed['config'] = $field['config'];
            if ($self_table_name == $table_name) {
                $this_method_filed['config']['comment'] = $field['comment'];
            }
            $this_method_filed['trend'] = 'in';
            $method->methodField()->save($this_method_filed);


        }

        foreach ($data['out_tables'] as $i => $table_name) {
            $this_method_filed = [];
            if (!$table_name || !$data['out_fields'][$i]) {
                continue;
            }
            $this_table = \app\auto\model\Table::getByName($table_name);
            $field = \app\auto\model\Field::where('name', $data['out_fields'][$i])->where('table_id', $this_table['id'])->find();
            $this_method_filed['field_id'] = $field['id'];
            $this_method_filed['config'] = $field['config'];
            if ($self_table_name == $table_name) {
                $this_method_filed['config']['comment'] = $field['comment'];
            }
            $this_method_filed['trend'] = 'out';
            $method->methodField()->save($this_method_filed);
        }

        return $method->id;
    }


    public function fastAdd()
    {
        $controller_id = input('controller_id');
        $this->fastAddProgress($controller_id);
        return success();
    }


    public function fastAll()
    {
        $app_id = 1;
        $controller_ids = \app\auto\model\Controller::where('app_id',$app_id)->column('id');
        foreach ($controller_ids as $controller_id){
            $this->fastAddProgress($controller_id);
        }
        return success();
    }


    private function fastAddProgress($controller_id){
        \app\auto\model\Method::destroy(function($query) use ($controller_id){
            $query->where('controller_id','=',$controller_id);
        });

        $controller = \app\auto\model\Controller::find($controller_id);
        $prefix = Str::snake($controller['name']) . '__';
        $self_table_name = env('DATABASE.PREFIX') . Str::snake($controller['name']);
        $self_table = \app\auto\model\Table::where('name', $self_table_name)->find();

        $self_field_names = \app\auto\model\Field::where('table_id', $self_table['id'])
            ->where('is_sys', 0)
            ->where('name','<>', 'pubid')
            ->where('name','<>', 'name')
            ->column('name');

        $add_names = ['name'];
        $order_field_exist = \app\auto\model\Field::where('table_id', $self_table['id'])
            ->where('name','=', 'sort')->find();

        if($order_field_exist){
            $add_names[] = 'sort';
        }

        $add_names = array_merge($add_names, $self_field_names);
        $add_update_fields = \app\auto\model\Field::where('table_id', $self_table['id'])
            ->where('name','in',$add_names)
            ->select();


        $list_names = $add_names;
//        $list_names[] = 'create_time';
        $list_names = array_merge($list_names, $self_field_names);

        $list_fields = \app\auto\model\Field::where('table_id', $self_table['id'])
            ->where('name','in',$list_names)
            ->select();

        // add方法
        $add = [
            "type" => "add",
            "request" => "post_view",
            "comment" => "新增",
            "name" => "add",
            "list_row" => "15",
            "style" => "",
            "title" => "新增",
            "msg" => "确认操作吗？",
            "is_iframe" => "1",
            "height" => "100%",
            "width" => "100%",
            "is_user_define" => "0",
            "controller_id" => $controller_id,
        ];
        foreach ($add_update_fields as $field) {
            $add['in_fields'][] = $field['name'];
            $add['in_tables'][] = $self_table_name;
            $add['in_alias'][] = $prefix . $field['name'];
            $this_alias = $prefix . $field['name'];
            $add['in_conditions'][] = "= input('{$this_alias}','')";
        }
        $add_id = $this->addProgress($add);



        // add方法
        $update = [
            "type" => "update",
            "request" => "post_view",
            "comment" => "修改",
            "name" => "update",
            "list_row" => "15",
            "style" => "",
            "title" => "修改",
            "msg" => "确认操作吗？",
            "is_iframe" => "1",
            "height" => "100%",
            "width" => "100%",
            "is_user_define" => "0",
            "controller_id" => $controller_id,
        ];
        foreach ($add_update_fields as $field) {
            $update['in_fields'][] = $field['name'];
            $update['in_tables'][] = $self_table_name;
            $update['in_alias'][] = $prefix . $field['name'];
            $this_alias = $prefix . $field['name'];
            $update['in_conditions'][] = "= input('{$this_alias}','')";
        }
        $update_id = $this->addProgress($update);


        // 删除方法
        $delete = [
            "type" => "delete",
            "request" => "get",
            "comment" => "删除",
            "name" => "delete",
            "list_row" => "15",
            "style" => "layui-btn-danger",
            "title" => "删除",
            "msg" => "确认删除操作吗？？",
            "is_iframe" => "0",
            "height" => "100%",
            "width" => "100%",
            "is_user_define" => "0",
            "controller_id" => $controller_id,
        ];
        $delete_id = $this->addProgress($delete);


        // list方法
        $list = [
            "type" => "list",
            "request" => "get_view",
            "comment" => "列表",
            "name" => "list",
            "list_row" => "15",
            "style" => "",
            "title" => "列表",
            "msg" => "确认操作吗？",
            "is_iframe" => "1",
            "height" => "100%",
            "width" => "100%",
            "is_user_define" => "0",
            "controller_id" => $controller_id,
        ];
        $list['out_fields'][] = 'id';
        $list['out_tables'][] = $self_table_name;
        $list['out_alias'][] = $prefix . 'id';
        $exist_name = in_array('name', array_column($list_fields->toArray(), 'name'));
        if($exist_name){
            $list['in_fields'][] = 'name';
            $list['in_tables'][] = $self_table_name;
            $list['in_alias'][] = $prefix . 'name';
            $name_in_alias = $prefix . 'name';
            $list['in_conditions'][] = "like input('{$name_in_alias}','')";
        }

        foreach ($list_fields as $field) {
            if($field['is_relation']){
                $relation_table_name = env('DATABASE.PREFIX') .  str_replace('_id', '', $field['name']);
                $list['out_fields'][] = 'name';
                $list['out_tables'][] = $relation_table_name;
                $list['out_alias'][] = str_replace('_id', '__name', $field['name']) ;

                $list['in_fields'][] = 'id';
                $list['in_tables'][] = $relation_table_name;
                $this_alias = str_replace(env('DATABASE.PREFIX'), '', $relation_table_name) . '__'. 'id';;
                $list['in_alias'][] = $this_alias;
                $list['in_conditions'][] = "= input('{$this_alias}','')";
            }else{
                $list['out_fields'][] = $field['name'];
                $list['out_tables'][] = $self_table_name;
                $list['out_alias'][] = $prefix . $field['name'];
            }

        }
        $list_id = $this->addProgress($list);
        $view_config = [
            'top' => [$add_id],
            'list' =>  [$update_id, $delete_id],
            'bottom' => [],
        ];
        \app\auto\model\Method::update([
            'id' => $list_id,
            'view_config' => $view_config
        ]);
    }


    public function update()
    {
        if (request()->isPost()) {
            $data = input();
            validate([
                'type|方法类型' => 'require',
                'request|请求类型' => 'require',
                'comment|方法中文名' => 'require',
                'name|方法英文名' => 'require',
                'is_user_define|是否自定义' => 'require',
            ])->check($data);
            $find = \app\auto\model\Method::where('name', $data['name'])
                ->where('id', '<>', $data['id'])
                ->where('controller_id', $data['controller_id'])->find();
            if ($find && $find['id'] != $data['id']) {
                return error('方法已经存在');
            }
            if ($data['msg'] === '') {
                unset($data['msg']);
            }
            if ($data['width'] === '') {
                unset($data['width']);
            }
            if ($data['height'] === '') {
                unset($data['height']);
            }
            $method = \app\auto\model\Method::update($data);

            MethodFiled::destroy(function ($query) use ($data) {
                $query->where('method_id', '=', $data['id']);
            });

            $controller = \app\auto\model\Controller::find($data['controller_id']);
            $self_table_name = env('DATABASE.PREFIX') . Str::snake($controller['name']);
            foreach ($data['in_tables'] as $i => $table_name) {
                $this_method_filed = [];
                if (!$table_name || !$data['in_fields'][$i]) {
                    continue;
                }
                $this_table = \app\auto\model\Table::getByName($table_name);
                $field = \app\auto\model\Field::where('name', $data['in_fields'][$i])->where('table_id', $this_table['id'])->find();
                $this_method_filed['field_id'] = $field['id'];
                $this_method_filed['condition'] = $data['in_conditions'][$i];
                $this_method_filed['config'] = $field['config'];
                if ($self_table_name == $table_name) {
                    $this_method_filed['config']['comment'] = $field['comment'];
                }
                $this_method_filed['trend'] = 'in';
                $method->methodField()->save($this_method_filed);
            }


            foreach ($data['out_tables'] as $i => $table_name) {
                $this_method_filed = [];
                if (!$table_name || !$data['out_fields'][$i]) {
                    continue;
                }
                $this_table = \app\auto\model\Table::getByName($table_name);
                $field = \app\auto\model\Field::where('name', $data['out_fields'][$i])->where('table_id', $this_table['id'])->find();
                $this_method_filed['field_id'] = $field['id'];
                $this_method_filed['config'] = $field['config'];
                if ($self_table_name == $table_name) {
                    $this_method_filed['config']['comment'] = $field['comment'];
                }
                $this_method_filed['trend'] = 'out';
                $method->methodField()->save($this_method_filed);
            }

            return success();
        } else {


            $id = input('id');
            $method = \app\auto\model\Method::find($id);
            $method = $method->toArray();
            View::assign('r', $method);


            $ins = MethodFiled::where('trend', 'in')->where('method_id', $id)->select();
            $in_arr = [];
            foreach ($ins as $in) {
                $in_field = \app\auto\model\Field::find($in['field_id']);
                $in_table = \app\auto\model\Table::find($in_field['table_id']);
                $in['table_name'] = $in_table['name'];
                $in['field_name'] = $in_field['name'];
                $in['fields'] = \app\auto\model\Field::where('table_id', $in_table['id'])->select();
                $in_arr[] = $in;
            }
            View::assign('in_arr', $in_arr);


            $outs = MethodFiled::where('trend', 'out')->where('method_id', $id)->select();
            $out_arr = [];
            foreach ($outs as $out) {
                $out_field = \app\auto\model\Field::find($out['field_id']);
                $out_table = \app\auto\model\Table::find($out_field['table_id']);
                $out['table_name'] = $out_table['name'];
                $out['field_name'] = $out_field['name'];
                $out['fields'] = \app\auto\model\Field::where('table_id', $out_table['id'])->select();
                $out['alias'] = str_replace(env('DATABASE.PREFIX'), '', $out_table['name']) . '__' . $out_field['name'];
                $out_arr[] = $out;
            }
            View::assign('out_arr', $out_arr);

            $controller_id = $method['controller_id'];
            $controller = \app\auto\model\Controller::find($controller_id);
            $table_name = Str::snake($controller->name);
            $table_name = env('DATABASE.PREFIX') . $table_name;
            $table_id = \app\auto\model\Table::where('name', $table_name)->value('id');
            $fields = \app\auto\model\Field::where('table_id', $table_id)->select();
            View::assign('table_name', $table_name);
            View::assign('fields', $fields);
            $tables = \app\auto\model\Table::select();
            View::assign('tables', $tables);
            return View::fetch();
        }
    }

    /**
     * field
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function field()
    {
        if(request()->isPost()){
            $data = input();

            $method = \app\auto\model\Method::find($data['id']);
            MethodFiled::destroy(function ($query) use ($data) {
                $query->where('method_id', '=', $data['id']);
            });

            $controller = \app\auto\model\Controller::find($method['controller_id']);
            $self_table_name = env('DATABASE.PREFIX') . Str::snake($controller['name']);


            foreach ($data['in'] as $field_id){
                $field =  \app\auto\model\Field::find($field_id);
                $this_method_filed['field_id'] = $field['id'];
                $table_name = $field->iTable->name;
                $alias_name = str_replace(env('DATABASE.PREFIX'), '', $table_name) . '__' . $field['name'];
                if($method['type'] == 'list'){
                    $data_express_name = 'id__' . $field_id;
                    $this_method_filed['condition'] = "$data[$data_express_name] input('{$alias_name}','')";
                }else{
                    $this_method_filed['condition'] = "= input('{$alias_name}','')";
                }

                $this_method_filed['config'] = $field['config'];
                if ($self_table_name == $table_name) {
                    $this_method_filed['config']['comment'] = $field['comment'];
                }
                $this_method_filed['trend'] = 'in';
                $method->methodField()->save($this_method_filed);
            }

            foreach ($data['out'] as $field_id){
                $field =  \app\auto\model\Field::find($field_id);
                $this_method_filed['field_id'] = $field['id'];
                $table_name = $field->iTable->name;
                $this_method_filed['config'] = $field['config'];
                if ($self_table_name == $table_name) {
                    $this_method_filed['config']['comment'] = $field['comment'];
                }
                $this_method_filed['trend'] = 'out';
                $method->methodField()->save($this_method_filed);
            }


            return success();
        }else{
            $method_id = input('id');
            $method = \app\auto\model\Method::find($method_id);
            View::assign('method', $method);
            $data = MethodFiled::where('method_id', $method_id)->select();
            $table_ids = [];
            $in_field_ids = [];
            $out_field_ids = [];
            $in_condition = [];
            if(!$data->isEmpty()){
                foreach ($data as $methodField){
                    $field = \app\auto\model\Field::find($methodField['field_id']);
                    $field['field'] = $field;
                    $table_ids[] = $field['table_id'];
                    if($methodField['trend'] == 'in') {
                        $in_field_ids[] = $methodField['field_id'];
                        $in_condition[$methodField['field_id']] = explode(' ', $methodField['condition'])['0'];
                    }else{
                        $out_field_ids[] = $methodField['field_id'];
                    }

                }
            }
            $table_ids = array_unique($table_ids);
            View::assign('table_ids', $table_ids);
            View::assign('in_field_ids', $in_field_ids);
            View::assign('out_field_ids', $out_field_ids);
            View::assign('in_condition', $in_condition);


            $controller = \app\auto\model\Controller::find($method['controller_id']);
            $self_table_name = env('DATABASE.PREFIX') . Str::snake($controller['name']);
            $self_table = \app\auto\model\Table::where('name', $self_table_name)->find();
            View::assign('self_table', $self_table);

            $tables = \app\auto\model\Table::where('id', 'in', $table_ids)
                ->where('name', '<>', $self_table_name)
                ->select();
            View::assign('tables', $tables);

            View::assign('data', $data);
            return View::fetch();
        }


    }


    public function delete()
    {
        $id = input('id');
        \app\auto\model\Method::destroy($id);
        return success();
    }


    /**
     * 根据表名获取字段options
     * getFieldOptionsByTableName
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getFieldOptionsByTableName(): string
    {
        $table_name = input('table_name');
        $table_name_no_prefix = str_replace(env('DATABASE.PREFIX'), '', $table_name);
        $table = \app\auto\model\Table::getByName($table_name);
        $table_id = $table['id'];
        $fields = \app\auto\model\Field::where('table_id', $table_id)->select();
        $html = '<option value="">请选择</option>';
        foreach ($fields as $field) {
            $html .= <<<EOF
<option value="{$field['name']}" data-alias="{$table_name_no_prefix}__{$field['name']}">{$field['comment']}</option>
EOF;
        }
        return $html;
    }


    /**
     * slot
     * @return Json|string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function slot()
    {
        if (request()->isPost()) {
            $id = input('id');
            $view_config = [
                'top' => input('top') ?: [],
                'list' => input('list') ?: [],
                'bottom' => input('bottom') ?: [],
            ];
            \app\auto\model\Method::update([
                'id' => $id,
                'view_config' => $view_config
            ]);
            return success();
        } else {
            $controller_ids = \app\auto\model\Controller::where('app_id', 1)->column('id');
            $methods = \app\auto\model\Method::where('controller_id', 'in', $controller_ids)->select();
            $res = [];
            foreach ($methods as $method) {
                $this_item['full'] = $method->controller->comment . '-' . $method->comment;
                $this_item['id'] = $method->id;
                $res[] = $this_item;
            }
            View::assign('method_arr', $res);
            $data = \app\auto\model\Method::find(input('id'));
            $data = $data->toArray();
            if (!$data['view_config']['top']) {
                $data['view_config']['top'] = [];
            }
            if (!$data['view_config']['list']) {
                $data['view_config']['list'] = [];
            }
            if (!$data['view_config']['bottom']) {
                $data['view_config']['bottom'] = [];
            }
            View::assign('data', $data['view_config']);
            return View::fetch();
        }
    }


}
